use std::env::Args;

use super::{CodeGenerator, Parser, VM, code_generator, lexer::Lexer, semantic_analyzer::{self, SemanticAnalyzer}};

#[derive(Debug, Default, Clone)]
pub struct Core {
    _cmm_file_path: Box<String>,
    _asm_file_path: Box<String>,
    _output_file_path: Box<String>,
}

impl Core {
    pub fn new() -> Self {
        Self {
            ..Default::default()
        }
    }
    pub fn main(&mut self) {
        self.input_arg();
        self.gen_code();
        self.exec_code();
    }
    /// 添加测试文件路径
    fn add_test_data(argv: &mut Vec<String>){
        if argv.len() < 2 {
            let root_dir = env!("CARGO_MANIFEST_DIR").to_string();
            let a = root_dir.clone() + "/test_file/testA.cmm";
            let b = root_dir.clone() + "/test_file/testB.cmm";
            let mut cur_file = a.clone();
            argv.push("i".to_string());
            argv.push(cur_file);

            let mut asm_path = root_dir + "main.out";
            argv.push("o".to_string());
            argv.push(asm_path.clone());
            argv.push("r".to_string());
            argv.push(asm_path);
        }
    }
    fn input_arg(&mut self) {
        let args = std::env::args();
        let mut argv = args.fold(vec![], |mut v, s| {
            v.push(s);
            v
        });
        //用来测试
        Core::add_test_data(&mut argv);
        println!("参数列表: {:?}", argv);
        let len = argv.len();
        let mut i = 1;
        while i < len {
            let arg = argv[i].clone();
            match arg.as_str() {
                "help" | "h" => {
                    println!("show this help message and exit");
                    i += 1;
                }
                "i" => {
                    println!("Input CMM File Path");
                    *self._cmm_file_path = argv.get(i + 1).expect("i后缺少参数").clone();
                    i += 2;
                }
                "o" => {
                    println!("Output ASM File Path");
                    *self._output_file_path = argv.get(i + 1).unwrap_or(&"a.out".to_string()).clone();
                    i += 2;
                }
                "r" => {
                    println!("Input ASM File Path (For Running)");
                    *self._asm_file_path = argv.get(i + 1).expect("r后缺少参数").clone();
                    i += 2;
                }
                _ => {
                    println!("参数跳过");
                    i += 1;
                }
            }
        }
    }
    fn gen_code(&self) {
        if !self._cmm_file_path.is_empty() {
            // CodeGenerator::new(
            //     &Parser::new(&*self._cmm_file_path).root(),
            //     &*self._output_asm_code_file_path,
            //     &*self._output_byte_code_file_path,
            // )
            // .generate_code();
            let lexer = Lexer::new(self._cmm_file_path.as_ref());
            let token_list = lexer.lexical_analysis();
            let mut parser = Parser::new(token_list);
            let root = parser.syntax_analysis();
            let semantic_analyzer = SemanticAnalyzer::new(&root);
            let symbol_table = semantic_analyzer.symbol_table();
            let mut code_generator = CodeGenerator::new(&root, &symbol_table);
            let code_list = code_generator.generate_code();
            super::io::output_instruction(self._output_file_path.as_ref(), &code_list);
        }
    }
    fn exec_code(&self) {
        if !self._asm_file_path.is_empty() {
            let code_list = super::io::parse_instruction_file(self._asm_file_path.as_ref());
            let mut vm = VM::new(&code_list);
            vm.run();
        }
    }
}
